package 结构型模式.组合模式;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * 主要组成部分
 * Component（抽象组件）
 * 声明组合中对象的接口
 * 适当情况下实现所有类共有接口的默认行为
 * 声明访问及管理子组件的接口
 * 
 * Leaf（叶子节点）
 * 表示组合中的叶子对象，没有子节点
 * 定义组合中原始对象的行为
 * 
 * Composite（复合组件）
 * 定义有子组件的组件行为
 * 存储子组件
 * 在Component接口中实现与子组件有关的操作
 */

interface IFileSystemComponent
{
	void use(String name);
	Double getSize();
	String getName();
}

class File implements IFileSystemComponent
{
	private String name;
	private Double size;

	File(String name, Double size) 
	{
		this.name = name;
		this.size = size;
	}
	
	@Override
	public void use(String name) {
		System.out.println(name+" 内存："+size);
	}

	@Override
	public Double getSize() {
		return size;
	}

	@Override
	public String getName() {
		return name;
	}
}

interface IDirectory
{
	public void addFile(IFileSystemComponent file);
	public void remove(String name);
}

class Directory implements IFileSystemComponent,IDirectory
{
	private String name;
	private Double size;
	List<IFileSystemComponent> lists;

	public Directory(String name)
	{
		lists = new ArrayList<IFileSystemComponent>();
		this.name = name;
	}
	

	@Override
	public String getName() {
		return name;
	}

	public void addFile(IFileSystemComponent file) 
	{
		lists.add(file);
	}
	
	public void remove(String name)
	{
		for(int i = 0;i < lists.size();i++)
		{
			if(lists.get(i).getName().equals(name))
				lists.remove(i);
		}
	}

	//内部类
	class Storage
	{
		IFileSystemComponent file;
		Integer index;
	}

	@Override
	public void use(String name) 
	{
		System.out.println(name+" 内存："+getSize());
	}

	@Override
	public Double getSize() 
	{
		//非递归
		//初始化操作
		Stack<Storage> stack = new Stack<>();
		Storage storage = new Storage();
		storage.file = this;
		storage.index = 0;
		stack.push(storage);
		Double resultSize = 0d;//结果

		while(!stack.empty())
		{
			Storage current = stack.pop();

			if(current.file instanceof File)
			{
				resultSize+=current.file.getSize();
			}
			else
			{
				Directory file = (Directory) current.file;
				if(current.index < file.lists.size())
				{
					IFileSystemComponent iFileSystemComponent = file.lists.get(current.index);
					Storage newStorage = new Storage();
					newStorage.file = iFileSystemComponent;
					newStorage.index = 0;
					current.index+=1; //向后指
					stack.push(current);//如果是文件夹则需要保留
					stack.push(newStorage);
				}
			}
		}
		setSize(resultSize);
		return size;
	}

	public void setSize(Double size) {
		this.size = size;
	}
}

public class Composite 
{
	public static void main(String[] args) 
	{
		Directory dir1 = new Directory("dir1");
		Directory dir2 = new Directory("dir2");
		Directory dir3 = new Directory("dir3");
		IFileSystemComponent file1 = new File("file1",new Double(50));
		IFileSystemComponent file2 = new File("file2",new Double(20));
		IFileSystemComponent file3 = new File("file3",new Double(30.5));
		IFileSystemComponent file4 = new File("file4",new Double(30.5));

		dir1.addFile(dir2);
		dir1.addFile(dir3);
		dir1.addFile(file4);
		
		dir2.addFile(file1);
		dir2.addFile(file2);
		dir3.addFile(file3);

		System.out.println("dir1文件夹内存:"+dir1.getSize());
		System.out.println("dir2文件夹内存:"+dir2.getSize());
	}
}